package com.jinlia.show.common.web.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 启动类上需开启 mvc注解
 */
@EnableWebMvc
@Configuration
public class WebDataConvertConfig implements WebMvcConfigurer {
    /**
     * 解决前端接受后端Long类型时 失真问题?
     * @param converters
     */
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        /**
         * 序列换成json时,将所有的long变成string
         * 因为js中得数字类型不能包含所有的java long值
         */
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        simpleModule.addSerializer(LocalDate.class, LocalDateConverter.instance);
        simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeConverter.instance);
        simpleModule.addSerializer(LocalTime.class, LocalTimeConverter.instance);
        objectMapper.registerModule(simpleModule)
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) //没有的属性忽略
                .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
        converters.add(jackson2HttpMessageConverter);
    }
    private static DateTimeFormatter dateTimeFormatterLocalDate = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    @JacksonStdImpl
    public static class LocalDateConverter extends ToStringSerializerBase {
        public static final LocalDateConverter instance = new LocalDateConverter();
        public LocalDateConverter() {
            super(Object.class);
        }
        public LocalDateConverter(Class<?> handledType) {
            super(handledType);
        }

        @Override
        public String valueToString(Object value) {
            return  dateTimeFormatterLocalDate.format((LocalDate) value);
        }
    }
    private static DateTimeFormatter dateTimeFormatterLocalDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @JacksonStdImpl
    public static class LocalDateTimeConverter extends ToStringSerializerBase {
        public static final LocalDateTimeConverter instance = new LocalDateTimeConverter();
        public LocalDateTimeConverter() {
            super(Object.class);
        }
        public LocalDateTimeConverter(Class<?> handledType) {
            super(handledType);
        }

        @Override
        public String valueToString(Object o) {
            return dateTimeFormatterLocalDateTime.format((LocalDateTime) o);
        }
    }
    private static DateTimeFormatter timeFormatterLocalDateTime = DateTimeFormatter.ofPattern("HH:mm:ss");
    @JacksonStdImpl
    public static class LocalTimeConverter extends ToStringSerializerBase {
        public static final LocalTimeConverter instance = new LocalTimeConverter();
        public LocalTimeConverter() {
            super(Object.class);
        }
        public LocalTimeConverter(Class<?> handledType) {
            super(handledType);
        }

        @Override
        public String valueToString(Object o) {
            return timeFormatterLocalDateTime.format((LocalTime) o);
        }
    }
}
